package com.bdqn.reflect.util;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * SimpleBeanConvertor
 *
 * @author LILIBO
 * @since 2024/7/2
 */
public class SimpleBeanConvertor {

    /**
     * 将Request请求参数封装为Java中的Bean
     *
     * @param request
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T parseRequest(HttpServletRequest request, Class<T> type) {
        Map paramMap = request.getParameterMap();
        if (paramMap.isEmpty()) {
            return null;
        }
        // 创建一个目标类型对象（例如：User类的实例）
        T target = null;
        try {
            // 创建一个目标类型对象
            target = type.newInstance();
            // 获取目标类中的所有公开方法
            Method[] methods = type.getMethods();
            for (Method method : methods) {
                // 找到以set开头的方法
                if (method.getName().startsWith("set")) {
                    // 获取方法的参数列表
                    Class<?>[] args = method.getParameterTypes();
                    // 找到只有一个参数的方法
                    if (args.length == 1) {
                        // 获取对象属性的set方法，将request中的参数对应赋值给属性
                        // setName -> name
                        String paramName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
                        // 查看所有参数的Map中是否存在key和对象的属性匹配的
                        if (paramMap.containsKey(paramName)) {
                            // 将HTTP请求中String类型的参数转换为对应实体类型（可能是：int String String[]）
                            Object value = parseValue((String[]) paramMap.get(paramName), args[0]);
                            // 使用目标对象target调用method方法，传递一个参数value
                            method.invoke(target, value);
                        } else if (Boolean.class == args[0] || boolean.class == args[0]) {
                            // 如果是boolean类型，不存在表示false
                            method.invoke(target, false);
                        }
                    }
                }
            }
        } catch (InstantiationException | IllegalAccessException | ParseException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return target;
    }

    /**
     * 将数组类型的数据进行转换
     *
     * @param values
     * @param type
     * @param <T>
     * @return
     * @throws ParseException
     */
    private static <T> Object parseValue(String[] values, Class<T> type) throws ParseException {
        T[] targetArr = null; // String[] targetArr ["Java", "C#", "Spring"] ; int[] targetArr [1, 2, 5]
        // 判断是否为数组类型
        if (type.isArray()) {
            // 获取到数组内容的类型
            Class componentType = type.getComponentType();
            targetArr = (T[]) Array.newInstance(componentType, values.length);
            for (int i = 0; i < values.length; i++) {
                targetArr[i] = (T) parseValue(values[i], componentType);
            }
        } else {
            // 将单个参数转换处理
            return parseValue(values[0], type);
        }
        return targetArr;
    }

    /**
     * 将String类型的参数值转换为相关属性的类型
     *
     * @param value 要转换的数据
     * @param type 对应的类型
     * @return
     */
    private static Object parseValue(String value, Class type) throws ParseException {
        if (value == null) {
            return null;
        }
        if (String.class == type) {
            return value;
        }
        if (boolean.class == type || Boolean.class == type) {
            if ("".equals(value) || "false".equals(value) || "0".equals(value)) {
                return false;
            }
            return true;
        }
        if (Date.class == type) {
            return new SimpleDateFormat("yyyy-MM-dd").parse(value);
        }
        if (char.class == type || Character.class == type) {
            return value.charAt(0);
        }
        if (int.class == type || Integer.class == type) {
            return Integer.valueOf(value); // value = "1" --> 1
        }
        if (long.class == type || Long.class == type) {
            return Long.valueOf(value); // value = "1" --> 1L
        }
        if (float.class == type || Float.class == type) {
            return Float.valueOf(value); // value = "1" --> 1F
        }
        if (double.class == type || Double.class == type) {
            return Double.valueOf(value); // value = "1" --> 1D
        }
        if (byte.class == type || short.class == type) {
            try {
                // byte | Byte -> Byte
                type = Class.forName("java.lang." + type.getName().substring(0, 1).toUpperCase() + type.getName().substring(1));
                if (type.getName().startsWith("java.lang.") || type.getName().startsWith("java.math.")) {
                    try {
                        // long l = new Long("9"); // 9
                        // 获取参数类型的构造函数（带一个String参数）
                        return type.getConstructor(String.class).newInstance(value);
                    } catch (Exception e) {
                        throw new UnsupportedTypeException(e);
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        return null;
    }

}
